// MyStringArray.cpp: implementation of the CStringsArray class.
//
//////////////////////////////////////////////////////////////////////

//#include "stdafx.h"
#include "Global_Function.h"
#include <fcntl.h>


#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
TCHAR abcChNil = '\0';
//ABC_STATIC_DATA int _abcInitData[] = { -1, 0, 0,  0  };
//ABC_STATIC_DATA CCStringData* _abcDataNil = (CCStringData*)&_abcInitData;
//LPCTSTR _abcPchNil = (LPCTSTR)(((BYTE*)&_abcInitData)+sizeof(CCStringData));

#define abcEmptyString CStrings()


#define TCHAR_ARG   TCHAR
#define WCHAR_ARG   WCHAR
#define CHAR_ARG    char
struct _AFX_DOUBLE  { BYTE doubleBits[sizeof(double)]; };

#ifdef _X86_
	#define DOUBLE_ARG  _AFX_DOUBLE
#else
	#define DOUBLE_ARG  double
#endif
#define FORCE_ANSI      0x10000
#define FORCE_UNICODE   0x20000
#define FORCE_INT64     0x40000

//////////////////////////////////////////////////////////////////////
// CStrings Class
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

//CArrays<_TABLE_CELL,_TABLE_CELL>* tCellPtr;
//CArrays<_LOGIC_CELL,_LOGIC_CELL>* lCellPtr;
	
//int _wcstombszs(char* mbstr, const wchar_t* wcstr, size_t count)
//{
//	if (count == 0 && mbstr != NULL)
//		return 0;

//	int result = ::WideCharToMultiByte(CP_ACP, 0, wcstr, -1,
//		mbstr, count, NULL, NULL);
//	if (result > 0)
//		mbstr[result-1] = 0;
//	return result;
//}

//int _mbstowcszs(wchar_t* wcstr, const char* mbstr, size_t count)
//{
//	if (count == 0 && wcstr != NULL)
//		return 0;

//	int result = ::MultiByteToWideChar(CP_ACP, 0, mbstr, -1,
//		wcstr, count);
//	if (result > 0)
//		wcstr[result-1] = 0;
//	return result;
//}

//BOOL AbcIsValidAddress(const void* lp,UINT nBytes, BOOL bReadWrite )
//{
//	return ( lp != NULL );
//}
//BOOL AbcIsValidString(LPCSTR lpsz, int nLength )
//{
//	if (lpsz == NULL)
//		return FALSE;
//	return ::IsBadStringPtr(lpsz, nLength) == 0;
//}

CStrings::CStrings()
{
    //Init();
}

CStrings::CStrings(const CStrings& stringSrc)
{
//	if (stringSrc.GetData()->nRefs >= 0)
//	{
//		m_pchData = stringSrc.m_pchData;
//		InterlockedIncrement(&GetData()->nRefs);
//	}
//	else
//	{
//		Init();
//		*this = stringSrc.m_pchData;
//	}
    m_pchData = stringSrc.m_pchData;
}

CStrings::CStrings(const std::string& stringSrc)
{
    m_pchData = stringSrc;
}

//CStrings::CStrings(LPCSTR lpsz)
//	{ Init(); *this = lpsz; }
CStrings::CStrings(const unsigned char* lpsz)
{
//    Init();
//    *this = (LPCSTR)lpsz;
    m_pchData = (char *)lpsz;
}

CStrings::CStrings(const char* lpsz)
{
    m_pchData = lpsz;
}

const CStrings& CStrings::operator=(const CStrings& stringSrc)
{
    m_pchData = stringSrc.m_pchData;
    return *this;
}

const CStrings& CStrings::operator=(const std::string& stringSrc)
{
    m_pchData = stringSrc;
    return *this;
}

const CStrings& CStrings::operator=(const char * stringSrc)
{
    m_pchData = stringSrc;
    return *this;
}

const CStrings& CStrings::operator=(const unsigned char * stringSrc)
{
    m_pchData = (char*)stringSrc;
    return *this;
}

//const CStrings& CStrings::operator=(TCHAR ch)
//{
//	AssignCopy(1, &ch);
//	return *this;
//}

//#ifdef _UNICODE
const CStrings& CStrings::operator=(char ch)
{ 
    //*this = (TCHAR)ch;
    m_pchData = ch;
	return *this; 
}
//#endif

//CStrings::CStrings(TCHAR ch, int nLength)
//{
//	Init();
//	if (nLength >= 1)
//	{
//		AllocBuffer(nLength);
//		memset(m_pchData, ch, nLength);
//	}
//}

//CStrings::CStrings(LPCTSTR lpch, int nLength)
//{
//	Init();
//	if (nLength != 0)
//	{
//		AllocBuffer(nLength);
//		memcpy(m_pchData, lpch, nLength*sizeof(TCHAR));
//	}
//}


CStrings::~CStrings()
{
//	if (GetData() != _abcDataNil)
//	{
//		if (InterlockedDecrement(&GetData()->nRefs) <= 0)
//			FreeData(GetData());
//	}
}


//void CStrings::Init()
//{
//	m_pchData = (LPTSTR)_abcPchNil;
//}

//CCStringData* CStrings::GetData() const
//{
//	return ((CCStringData*)m_pchData)-1;
//}

int CStrings::GetLength() const	
{
    //return GetData()->nDataLength;
    return static_cast<int>(m_pchData.size());
}
//int PASCAL CStrings::SafeStrlen(LPCTSTR lpsz)
//	{ return (lpsz == NULL) ? 0 : lstrlen(lpsz); }
//int CStrings::GetAllocLength() const
//	{ return GetData()->nAllocLength; }
BOOL CStrings::IsEmpty() const
{
    //return GetData()->nDataLength == 0;
    return m_pchData.size() == 0;
}

//int CStrings::Compare(LPCTSTR lpsz) const
//	{ return _tcscmp(m_pchData, lpsz); }    // MBCS/Unicode aware
//int CStrings::CompareNoCase(LPCTSTR lpsz) const
//	{ return _tcsicmp(m_pchData, lpsz); }   // MBCS/Unicode aware
// CString::Collate is often slower than Compare but is MBSC/Unicode
//  aware as well as locale-sensitive with respect to sort order.
//int CStrings::Collate(LPCTSTR lpsz) const
//	{ return _tcscoll(m_pchData, lpsz); }   // locale sensitive
//int CStrings::CollateNoCase(LPCTSTR lpsz) const
//	{ return _tcsicoll(m_pchData, lpsz); }   // locale sensitive


CStrings operator+(const CStrings& string1,const CStrings& string2)
{
    //CStrings s;
//	s.ConcatCopy(string1.GetData()->nDataLength, string1.m_pchData,
//		string2.GetData()->nDataLength, string2.m_pchData);

    return CStrings(string1.m_pchData + string2.m_pchData);
}

CStrings operator+(const CStrings& string, LPCTSTR lpsz)
{
	CStrings s;
    //s.ConcatCopy(string.GetData()->nDataLength, string.m_pchData,
    //	CStrings::SafeStrlen(lpsz), lpsz);
    s.m_pchData = string.m_pchData + lpsz;
	return s;
}

CStrings operator+(LPCTSTR lpsz, const CStrings& string)
{
	CStrings s;
    //s.ConcatCopy(CStrings::SafeStrlen(lpsz), lpsz, string.GetData()->nDataLength,
    //	string.m_pchData);
    s.m_pchData = lpsz + string.m_pchData;
	return s;
}

//CStrings operator+(const CStrings& string, TCHAR ch)
//{
//	CStrings s;
//	s.ConcatCopy(string.GetData()->nDataLength, string.m_pchData, 1, &ch);
//	return s;
//}

//CStrings operator+(TCHAR ch, const CStrings& string)
//{
//	CStrings s;
//	s.ConcatCopy(1, &ch, string.GetData()->nDataLength, string.m_pchData);
//	return s;
//}

//void CStrings::AllocCopy(CStrings& dest, int nCopyLen, int nCopyIndex,int nExtraLen) const
//{
//	// will clone the data attached to this string
//	// allocating 'nExtraLen' characters
//	// Places results in uninitialized string 'dest'
//	// Will copy the part or all of original data to start of new string

//	int nNewLen = nCopyLen + nExtraLen;
//	if (nNewLen == 0)
//	{
//		dest.Init();
//	}
//	else
//	{
//		dest.AllocBuffer(nNewLen);
//		memcpy(dest.m_pchData, m_pchData+nCopyIndex, nCopyLen*sizeof(TCHAR));
//	}
//}

CStrings CStrings::Mid(int nFirst) const
{
    //return Mid(nFirst, GetData()->nDataLength - nFirst);
    return Mid(nFirst, GetLength() - nFirst);
}

CStrings CStrings::Mid(int nFirst, int nCount) const
{
	// out-of-bounds requests return sensible things
	if (nFirst < 0)
		nFirst = 0;
	if (nCount < 0)
		nCount = 0;

    if (nFirst + nCount > GetLength())
        nCount = GetLength() - nFirst;
    if (nFirst > GetLength())
		nCount = 0;


	// optimize case of returning entire string
    if (nFirst == 0 && nFirst + nCount == GetLength())
		return *this;

    //CStrings dest;
    //AllocCopy(dest, nCount, nFirst, 0);
    //return dest;
    return CStrings{m_pchData.substr(nFirst, nCount)};
}

CStrings CStrings::Right(int nCount) const
{
	if (nCount < 0)
		nCount = 0;
    if (nCount >= GetLength())
		return *this;

    //CStrings dest;
    //AllocCopy(dest, nCount, GetData()->nDataLength-nCount, 0);
    //return dest;
    auto nFirst = GetLength() - nCount;
    return CStrings{m_pchData.substr(nFirst, nCount)};
}

CStrings CStrings::Left(int nCount) const
{
	if (nCount < 0)
		nCount = 0;
    if (nCount >= GetLength())
		return *this;

    //CStrings dest;
    //AllocCopy(dest, nCount, 0, 0);
    //return dest;
    return CStrings{m_pchData.substr(0, nCount)};
}

//void CStrings::FormatV(LPCTSTR lpszFormat, va_list argList)
//{
//	va_list argListSave = argList;
	
//	// make a guess at the maximum length of the resulting string
//	int nMaxLen = 0;
//	for (LPCTSTR lpsz = lpszFormat; *lpsz != '\0'; lpsz = _tcsinc(lpsz))
//	{
//		// handle '%' character, but watch out for '%%'
//		if (*lpsz != '%' || *(lpsz = _tcsinc(lpsz)) == '%')
//		{
//			nMaxLen += _tclen(lpsz);
//			continue;
//		}

//		int nItemLen = 0;

//		// handle '%' character with format
//		int nWidth = 0;
//		for (; *lpsz != '\0'; lpsz = _tcsinc(lpsz))
//		{
//			// check for valid flags
//			if (*lpsz == '#')
//				nMaxLen += 2;   // for '0x'
//			else if (*lpsz == '*')
//				nWidth = va_arg(argList, int);
//			else if (*lpsz == '-' || *lpsz == '+' || *lpsz == '0' ||
//				*lpsz == ' ')
//				;
//			else // hit non-flag character
//				break;
//		}
//		// get width and skip it
//		if (nWidth == 0)
//		{
//			// width indicated by
//			nWidth = _ttoi(lpsz);
//			for (; *lpsz != '\0' && _istdigit(*lpsz); lpsz = _tcsinc(lpsz))
//				;
//		}

//		int nPrecision = 0;
//		if (*lpsz == '.')
//		{
//			// skip past '.' separator (width.precision)
//			lpsz = _tcsinc(lpsz);

//			// get precision and skip it
//			if (*lpsz == '*')
//			{
//				nPrecision = va_arg(argList, int);
//				lpsz = _tcsinc(lpsz);
//			}
//			else
//			{
//				nPrecision = _ttoi(lpsz);
//				for (; *lpsz != '\0' && _istdigit(*lpsz); lpsz = _tcsinc(lpsz))
//					;
//			}
//		}

//		// should be on type modifier or specifier
//		int nModifier = 0;
//		if (_tcsncmp(lpsz, _T("I64"), 3) == 0)
//		{
//			lpsz += 3;
//			nModifier = FORCE_INT64;
//		}
//		else
//		{
//			switch (*lpsz)
//			{
//			// modifiers that affect size
//			case 'h':
//				nModifier = FORCE_ANSI;
//				lpsz = _tcsinc(lpsz);
//				break;
//			case 'l':
//				nModifier = FORCE_UNICODE;
//				lpsz = _tcsinc(lpsz);
//				break;

//			// modifiers that do not affect size
//			case 'F':
//			case 'N':
//			case 'L':
//				lpsz = _tcsinc(lpsz);
//				break;
//			}
//		}

//		// now should be on specifier
//		switch (*lpsz | nModifier)
//		{
//		// single characters
//		case 'c':
//		case 'C':
//			nItemLen = 2;
//			va_arg(argList, TCHAR_ARG);
//			break;
//		case 'c'|FORCE_ANSI:
//		case 'C'|FORCE_ANSI:
//			nItemLen = 2;
//			va_arg(argList, CHAR_ARG);
//			break;
//		case 'c'|FORCE_UNICODE:
//		case 'C'|FORCE_UNICODE:
//			nItemLen = 2;
//			va_arg(argList, WCHAR_ARG);
//			break;

//		// strings
//		case 's':
//			{
//				LPCTSTR pstrNextArg = va_arg(argList, LPCTSTR);
//				if (pstrNextArg == NULL)
//				   nItemLen = 6;  // "(null)"
//				else
//				{
//				   nItemLen = lstrlen(pstrNextArg);
//				   nItemLen = max(1, nItemLen);
//				}
//			}
//			break;

//		case 'S':
//			{
//#ifndef _UNICODE
//				LPWSTR pstrNextArg = va_arg(argList, LPWSTR);
//				if (pstrNextArg == NULL)
//				   nItemLen = 6;  // "(null)"
//				else
//				{
//				   nItemLen = wcslen(pstrNextArg);
//				   nItemLen = max(1, nItemLen);
//				}
//#else
//				LPCSTR pstrNextArg = va_arg(argList, LPCSTR);
//				if (pstrNextArg == NULL)
//				   nItemLen = 6; // "(null)"
//				else
//				{
//				   nItemLen = lstrlenA(pstrNextArg);
//				   nItemLen = max(1, nItemLen);
//				}
//#endif
//			}
//			break;

//		case 's'|FORCE_ANSI:
//		case 'S'|FORCE_ANSI:
//			{
//				LPCSTR pstrNextArg = va_arg(argList, LPCSTR);
//				if (pstrNextArg == NULL)
//				   nItemLen = 6; // "(null)"
//				else
//				{
//				   nItemLen = lstrlenA(pstrNextArg);
//				   nItemLen = max(1, nItemLen);
//				}
//			}
//			break;

//		case 's'|FORCE_UNICODE:
//		case 'S'|FORCE_UNICODE:
//			{
//				LPWSTR pstrNextArg = va_arg(argList, LPWSTR);
//				if (pstrNextArg == NULL)
//				   nItemLen = 6; // "(null)"
//				else
//				{
//				   nItemLen = wcslen(pstrNextArg);
//				   nItemLen = max(1, nItemLen);
//				}
//			}
//			break;
//		}

//		// adjust nItemLen for strings
//		if (nItemLen != 0)
//		{
//			if (nPrecision != 0)
//				nItemLen = min(nItemLen, nPrecision);
//			nItemLen = max(nItemLen, nWidth);
//		}
//		else
//		{
//			switch (*lpsz)
//			{
//			// integers
//			case 'd':
//			case 'i':
//			case 'u':
//			case 'x':
//			case 'X':
//			case 'o':
//				if (nModifier & FORCE_INT64)
//					va_arg(argList, __int64);
//				else
//					va_arg(argList, int);
//				nItemLen = 32;
//				nItemLen = max(nItemLen, nWidth+nPrecision);
//				break;

//			case 'e':
//			case 'g':
//			case 'G':
//				va_arg(argList, DOUBLE_ARG);
//				nItemLen = 128;
//				nItemLen = max(nItemLen, nWidth+nPrecision);
//				break;

//			case 'f':
//				va_arg(argList, DOUBLE_ARG);
//				nItemLen = 128; // width isn't truncated
//				// 312 == strlen("-1+(309 zeroes).")
//				// 309 zeroes == max precision of a double
//				nItemLen = max(nItemLen, 312+nPrecision);
//				break;

//			case 'p':
//				va_arg(argList, void*);
//				nItemLen = 32;
//				nItemLen = max(nItemLen, nWidth+nPrecision);
//				break;

//			// no output
//			case 'n':
//				va_arg(argList, int*);
//				break;

//			default:
//				break;
//			}
//		}

//		// adjust nMaxLen for output nItemLen
//		nMaxLen += nItemLen;
//	}
//	GetBuffer(nMaxLen);
//	ReleaseBuffer();
//	va_end(argListSave);
//}

//void __cdecl CStrings::Format(LPCTSTR lpszFormat, ...)
//{
//	va_list argList;
//	va_start(argList, lpszFormat);
//	FormatV(lpszFormat, argList);
//	va_end(argList);

//}

//TCHAR CStrings::GetAt(int nIndex) const
char CStrings::GetAt(int nIndex) const
{
	return m_pchData[nIndex];
}

//TCHAR CStrings::operator[](int nIndex) const
char CStrings::operator[](int nIndex) const
{
	// same as GetAt
	return m_pchData[nIndex];
}
//void CStrings::AllocBeforeWrite(int nLen)
//{
//	if (GetData()->nRefs > 1 || nLen > GetData()->nAllocLength)
//	{
//		Release();
//		AllocBuffer(nLen);
//	}
//}
//void CStrings::AssignCopy(int nSrcLen, LPCTSTR lpszSrcData)
//{
//	AllocBeforeWrite(nSrcLen);
//	memcpy(m_pchData, lpszSrcData, nSrcLen*sizeof(TCHAR));
//	GetData()->nDataLength = nSrcLen;
//	m_pchData[nSrcLen] = '\0';
//}
//const CStrings& CStrings::operator=(const CStrings& stringSrc)
//{
//	if (m_pchData != stringSrc.m_pchData)
//	{
//		if ((GetData()->nRefs < 0 && GetData() != _abcDataNil) ||
//			stringSrc.GetData()->nRefs < 0)
//		{
//			// actual copy necessary since one of the strings is locked
//			AssignCopy(stringSrc.GetData()->nDataLength, stringSrc.m_pchData);
//		}
//		else
//		{
//			// can just copy references around
//			Release();
//			m_pchData = stringSrc.m_pchData;
//			InterlockedIncrement(&GetData()->nRefs);
//		}
//	}
//	return *this;
//}

//const CStrings& CStrings::operator=(LPCTSTR lpsz)
//{
//	AssignCopy(SafeStrlen(lpsz), lpsz);
//	return *this;
//}
//const CStrings& CStrings::operator=(LPCWSTR lpsz)
//{
//	int nSrcLen = lpsz != NULL ? wcslen(lpsz) : 0;
//	AllocBeforeWrite(nSrcLen*2);
//	_wcstombszs(m_pchData, lpsz, (nSrcLen*2)+1);
//	ReleaseBuffer();
//	return *this;
//}
//const CStrings& CStrings::operator=(const unsigned char* lpsz)
//{
//	*this = (LPCSTR)lpsz;
//	return *this;
//}

//void CStrings::CopyBeforeWrite()
//{
//	if (GetData()->nRefs > 1)
//	{
//		CCStringData* pData = GetData();
//		Release();
//		AllocBuffer(pData->nDataLength);
//		memcpy(m_pchData, pData->data(), (pData->nDataLength+1)*sizeof(TCHAR));
//	}
//}

//LPTSTR CStrings::GetBuffer(int nMinBufLength)
//{
//	if (GetData()->nRefs > 1 || nMinBufLength > GetData()->nAllocLength)
//	{
//		// we have to grow the buffer
//		CCStringData* pOldData = GetData();
//		int nOldLen = GetData()->nDataLength;   // AllocBuffer will tromp it
//		if (nMinBufLength < nOldLen)
//			nMinBufLength = nOldLen;
//		AllocBuffer(nMinBufLength);
//		memcpy(m_pchData, pOldData->data(), (nOldLen+1)*sizeof(TCHAR));
//		GetData()->nDataLength = nOldLen;
//		CStrings::Release(pOldData);
//	}
//	// return a pointer to the character storage for this string
//	return m_pchData;
//}

char const* CStrings::GetBuffer(int nMinBufLength)
{
    if(nMinBufLength < 0 || nMinBufLength > m_pchData.size())
        return m_pchData.data();

    // return a pointer to the character storage for this string
    return m_pchData.data()+nMinBufLength;
}

//void CStrings::ReleaseBuffer(int nNewLength)
//{
//	CopyBeforeWrite();  // just in case GetBuffer was not called

//	if (nNewLength == -1)
//		nNewLength = lstrlen(m_pchData); // zero terminated

//	GetData()->nDataLength = nNewLength;
//	m_pchData[nNewLength] = '\0';
//}

//LPTSTR CStrings::GetBufferSetLength(int nNewLength)
//{
//	GetBuffer(nNewLength);
//	GetData()->nDataLength = nNewLength;
//	m_pchData[nNewLength] = '\0';
//	return m_pchData;
//}

//void CStrings::Release()
//{
//	if (GetData() != _abcDataNil)
//	{
//		if (InterlockedDecrement(&GetData()->nRefs) <= 0)
//			FreeData(GetData());
//		Init();
//	}
//}

//void CStrings::Release(CCStringData* pData)
//{
//	if (pData != _abcDataNil)
//	{
//		if (InterlockedDecrement(&pData->nRefs) <= 0)
//			FreeData(pData);
//	}
//}

void CStrings::Empty()
{
//	if (GetData()->nDataLength == 0)
//		return;
//	if (GetData()->nRefs >= 0)
//		Release();
//	else
//		*this = &abcChNil;
    m_pchData.clear();
}


//void CStrings::AllocBuffer(int nLen)
//// always allocate one extra character for '\0' termination
//// assumes [optimistically] that data length will equal allocation length
//{
//	if (nLen == 0)
//		Init();
//	else
//	{
//		CCStringData* pData;
//		{
//			pData = (CCStringData*)
//				new BYTE[sizeof(CCStringData) + (nLen+1)*sizeof(TCHAR)];
//			pData->nAllocLength = nLen;
//		}
//		pData->nRefs = 1;
//		pData->data()[nLen] = '\0';
//		pData->nDataLength = nLen;
//		m_pchData = pData->data();
//	}
//}

//void CStrings::ConcatCopy(int nSrc1Len, LPCTSTR lpszSrc1Data,
//	int nSrc2Len, LPCTSTR lpszSrc2Data)
//{
//  // -- master concatenation routine
//  // Concatenate two sources
//  // -- assume that 'this' is a new CString object

//	int nNewLen = nSrc1Len + nSrc2Len;
//	if (nNewLen != 0)
//	{
//		AllocBuffer(nNewLen);
//		memcpy(m_pchData, lpszSrc1Data, nSrc1Len*sizeof(TCHAR));
//		memcpy(m_pchData+nSrc1Len, lpszSrc2Data, nSrc2Len*sizeof(TCHAR));
//	}
//}

//void CStrings::ConcatInPlace(int nSrcLen, LPCTSTR lpszSrcData)
//{
//	//  -- the main routine for += operators

//	// concatenating an empty string is a no-op!
//	if (nSrcLen == 0)
//		return;

//	// if the buffer is too small, or we have a width mis-match, just
//	//   allocate a new buffer (slow but sure)
//	if (GetData()->nRefs > 1 || GetData()->nDataLength + nSrcLen > GetData()->nAllocLength)
//	{
//		// we have to grow the buffer, use the ConcatCopy routine
//		CCStringData* pOldData = GetData();
//		ConcatCopy(GetData()->nDataLength, m_pchData, nSrcLen, lpszSrcData);
//		CStrings::Release(pOldData);
//	}
//	else
//	{
//		// fast concatenation when buffer big enough
//		memcpy(m_pchData+GetData()->nDataLength, lpszSrcData, nSrcLen*sizeof(TCHAR));
//		GetData()->nDataLength += nSrcLen;
//		m_pchData[GetData()->nDataLength] = '\0';
//	}
//}


const CStrings& CStrings::operator+=(const char * lpsz)
{
    //ConcatInPlace(SafeStrlen(lpsz), lpsz);
    m_pchData += lpsz;
	return *this;
}

const CStrings& CStrings::operator+=(char ch)
{
    //ConcatInPlace(1, &ch);
    m_pchData += ch;
    return *this;
}

const CStrings& CStrings::operator+=(const CStrings& str)
{
    //ConcatInPlace(string.GetData()->nDataLength, string.m_pchData);
    m_pchData += str.m_pchData;
	return *this;
}


//void CStrings::FreeData(CCStringData* pData)
//{
//	delete[] (BYTE*)pData;
//}

///////////////////////////////////////////////////////////////////////////////
// Commonly used routines (rarely used routines in STREX.CPP)
//////////////////////////////////////////////////////////////////////////////
// Finding


int CStrings::Find(char ch) const
{
	return Find(ch, 0);
}

int CStrings::Find(char ch, int nStart) const
{
//	int nLength = GetData()->nDataLength;
//	if (nStart >= nLength)
//		return -1;

//	// find first single character
//	LPTSTR lpsz = _tcschr(m_pchData + nStart, (_TUCHAR)ch);

//	// return -1 if not found and index otherwise
//	return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);

    int nLength = GetLength();
    if(nStart >= nLength)
        return -1;
    auto pos = m_pchData.find(ch, nStart);
    if(pos != std::string::npos)
        return pos;
    return -1;
}

//int CStrings::FindOneOf(LPCTSTR lpszCharSet) const
//{
//	LPTSTR lpsz = _tcspbrk(m_pchData, lpszCharSet);
//	return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
//}

int CStrings::ReverseFind(char ch) const
{
	// find last single character
    //LPTSTR lpsz = _tcsrchr(m_pchData, (_TUCHAR) ch);

	// return -1 if not found, distance from beginning otherwise
    //return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);

    auto pos = m_pchData.rfind(ch);
    if(pos != std::string::npos)
        return pos;
    return -1;
}

int CStrings::Find(LPCTSTR lpszSub) const
{
	return Find(lpszSub, 0);
}

int CStrings::Find(LPCTSTR lpszSub, int nStart) const
{
//	int nLength = GetData()->nDataLength;
//	if (nStart > nLength)
//		return -1;

//	// find first matching substring
//	LPTSTR lpsz = _tcsstr(m_pchData + nStart, lpszSub);

//	// return -1 for not found, distance from beginning otherwise
//	return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);

    int nLength = GetLength();
    if(nStart >= nLength)
        return -1;
    auto pos = m_pchData.find(lpszSub, nStart);
    if(pos != std::string::npos)
        return pos;
    return -1;
}

void CStrings::MakeUpper()
{
    //CopyBeforeWrite();
    //_tcsupr(m_pchData);
    for(auto &c : m_pchData)
        c = toupper(c);
}

void CStrings::MakeLower()
{
    //CopyBeforeWrite();
    //_tcslwr(m_pchData);
    for(auto &c : m_pchData)
        c = tolower(c);
}

void CStrings::MakeReverse()
{
    //CopyBeforeWrite();
    //_tcsrev(m_pchData);
    auto tmp = std::string{m_pchData.rbegin(), m_pchData.rend()};
    m_pchData = tmp;
}

//void CStrings::SetAt(int nIndex, TCHAR ch)
void CStrings::SetAt(int nIndex, char ch)
{
    //CopyBeforeWrite();
	m_pchData[nIndex] = ch;
}
//void CStrings::TrimRight(LPCTSTR lpszTargetList)
//{
//	// find beginning of trailing matches
//	// by starting at beginning (DBCS aware)

//	CopyBeforeWrite();
//	LPTSTR lpsz = m_pchData;
//	LPTSTR lpszLast = NULL;

//	while (*lpsz != '\0')
//	{
//		if (_tcschr(lpszTargetList, *lpsz) != NULL)
//		{
//			if (lpszLast == NULL)
//				lpszLast = lpsz;
//		}
//		else
//			lpszLast = NULL;
//		lpsz = _tcsinc(lpsz);
//	}

//	if (lpszLast != NULL)
//	{
//		// truncate at left-most matching character
//		*lpszLast = '\0';
//		GetData()->nDataLength = lpszLast - m_pchData;
//	}
//}

//void CStrings::TrimRight(TCHAR chTarget)
//{
//	// find beginning of trailing matches
//	// by starting at beginning (DBCS aware)

//	CopyBeforeWrite();
//	LPTSTR lpsz = m_pchData;
//	LPTSTR lpszLast = NULL;

//	while (*lpsz != '\0')
//	{
//		if (*lpsz == chTarget)
//		{
//			if (lpszLast == NULL)
//				lpszLast = lpsz;
//		}
//		else
//			lpszLast = NULL;
//		lpsz = _tcsinc(lpsz);
//	}

//	if (lpszLast != NULL)
//	{
//		// truncate at left-most matching character
//		*lpszLast = '\0';
//		GetData()->nDataLength = lpszLast - m_pchData;
//	}
//}

void CStrings::TrimRight()
{
	// find beginning of trailing spaces by starting at beginning (DBCS aware)

//	CopyBeforeWrite();
//	LPTSTR lpsz = m_pchData;
//	LPTSTR lpszLast = NULL;

//	while (*lpsz != '\0')
//	{
//		if (_istspace(*lpsz))
//		{
//			if (lpszLast == NULL)
//				lpszLast = lpsz;
//		}
//		else
//			lpszLast = NULL;
//		lpsz = _tcsinc(lpsz);
//	}

//	if (lpszLast != NULL)
//	{
//		// truncate at trailing space start
//		*lpszLast = '\0';
//		GetData()->nDataLength = lpszLast - m_pchData;
//	}

    auto pos = find_last_not_sp(m_pchData.begin(), m_pchData.end());
    if(pos != m_pchData.end())
        m_pchData.erase(pos);
}

//void CStrings::TrimLeft(LPCTSTR lpszTargets)
//{
//	// if we're not trimming anything, we're not doing any work
//	if (SafeStrlen(lpszTargets) == 0)
//		return;

//	CopyBeforeWrite();
//	LPCTSTR lpsz = m_pchData;

//	while (*lpsz != '\0')
//	{
//		if (_tcschr(lpszTargets, *lpsz) == NULL)
//			break;
//		lpsz = _tcsinc(lpsz);
//	}

//	if (lpsz != m_pchData)
//	{
//		// fix up data and length
//		int nDataLength = GetData()->nDataLength - (lpsz - m_pchData);
//		memmove(m_pchData, lpsz, (nDataLength+1)*sizeof(TCHAR));
//		GetData()->nDataLength = nDataLength;
//	}
//}

//void CStrings::TrimLeft(TCHAR chTarget)
//{
//	// find first non-matching character

//	CopyBeforeWrite();
//	LPCTSTR lpsz = m_pchData;

//	while (chTarget == *lpsz)
//		lpsz = _tcsinc(lpsz);

//	if (lpsz != m_pchData)
//	{
//		// fix up data and length
//		int nDataLength = GetData()->nDataLength - (lpsz - m_pchData);
//		memmove(m_pchData, lpsz, (nDataLength+1)*sizeof(TCHAR));
//		GetData()->nDataLength = nDataLength;
//	}
//}

void CStrings::TrimLeft()
{
	// find first non-space character

//	CopyBeforeWrite();
//	LPCTSTR lpsz = m_pchData;

//	while (_istspace(*lpsz))
//		lpsz = _tcsinc(lpsz);

//	if (lpsz != m_pchData)
//	{
//		// fix up data and length
//		int nDataLength = GetData()->nDataLength - (lpsz - m_pchData);
//		memmove(m_pchData, lpsz, (nDataLength+1)*sizeof(TCHAR));
//		GetData()->nDataLength = nDataLength;
//	}
    auto pos = find_not_sp(m_pchData.begin(), m_pchData.end());
    if(pos != m_pchData.begin())
        m_pchData.erase(m_pchData.begin(), pos);
}
//////////////////////////////////////////////////////////////////////////////
// Advanced manipulation

int CStrings::Delete(int nIndex, int nCount /* = 1 */)
{
//	if (nIndex < 0)
//		nIndex = 0;
//	int nNewLength = GetData()->nDataLength;
//	if (nCount > 0 && nIndex < nNewLength)
//	{
//		CopyBeforeWrite();
//		int nBytesToCopy = nNewLength - (nIndex + nCount) + 1;

//		memcpy(m_pchData + nIndex,
//			m_pchData + nIndex + nCount, nBytesToCopy * sizeof(TCHAR));
//		GetData()->nDataLength = nNewLength - nCount;
//	}

//	return nNewLength;
    m_pchData.erase(nIndex, nCount);
    return GetLength();
}

int CStrings::Insert(int nIndex, char ch)
{
//	CopyBeforeWrite();

//	if (nIndex < 0)
//		nIndex = 0;

//	int nNewLength = GetData()->nDataLength;
//	if (nIndex > nNewLength)
//		nIndex = nNewLength;
//	nNewLength++;

//	if (GetData()->nAllocLength < nNewLength)
//	{
//		CCStringData* pOldData = GetData();
//		LPTSTR pstr = m_pchData;
//		AllocBuffer(nNewLength);
//		memcpy(m_pchData, pstr, (pOldData->nDataLength+1)*sizeof(TCHAR));
//		CStrings::Release(pOldData);
//	}

//	// move existing bytes down
//	memcpy(m_pchData + nIndex + 1,
//		m_pchData + nIndex, (nNewLength-nIndex)*sizeof(TCHAR));
//	m_pchData[nIndex] = ch;
//	GetData()->nDataLength = nNewLength;

//	return nNewLength;
    m_pchData.insert(nIndex, 1, ch);
    return GetLength();
}

int CStrings::Insert(int nIndex, LPCTSTR pstr)
{
//	if (nIndex < 0)
//		nIndex = 0;

//	int nInsertLength = SafeStrlen(pstr);
//	int nNewLength = GetData()->nDataLength;
//	if (nInsertLength > 0)
//	{
//		CopyBeforeWrite();
//		if (nIndex > nNewLength)
//			nIndex = nNewLength;
//		nNewLength += nInsertLength;

//		if (GetData()->nAllocLength < nNewLength)
//		{
//			CCStringData* pOldData = GetData();
//			LPTSTR pstr = m_pchData;
//			AllocBuffer(nNewLength);
//			memcpy(m_pchData, pstr, (pOldData->nDataLength+1)*sizeof(TCHAR));
//			CStrings::Release(pOldData);
//		}

//		// move existing bytes down
//		memcpy(m_pchData + nIndex + nInsertLength,
//			m_pchData + nIndex,
//			(nNewLength-nIndex-nInsertLength+1)*sizeof(TCHAR));
//		memcpy(m_pchData + nIndex,
//			pstr, nInsertLength*sizeof(TCHAR));
//		GetData()->nDataLength = nNewLength;
//	}

//	return nNewLength;

    m_pchData.insert(nIndex, pstr);
    return GetLength();
}

//int CStrings::Replace(TCHAR chOld, TCHAR chNew)
//{
//	int nCount = 0;

//	// short-circuit the nop case
//	if (chOld != chNew)
//	{
//		// otherwise modify each character that matches in the string
//		CopyBeforeWrite();
//		LPTSTR psz = m_pchData;
//		LPTSTR pszEnd = psz + GetData()->nDataLength;
//		while (psz < pszEnd)
//		{
//			// replace instances of the specified character only
//			if (*psz == chOld)
//			{
//				*psz = chNew;
//				nCount++;
//			}
//			psz = _tcsinc(psz);
//		}
//	}
//	return nCount;
//}

int CStrings::Replace(LPCTSTR lpszOld, LPCTSTR lpszNew)
{
	// can't have empty or NULL lpszOld

//	int nSourceLen = SafeStrlen(lpszOld);
//	if (nSourceLen == 0)
//		return 0;
//	int nReplacementLen = SafeStrlen(lpszNew);

	// loop once to figure out the size of the result string
	int nCount = 0;
//	LPTSTR lpszStart = m_pchData;
//	LPTSTR lpszEnd = m_pchData + GetData()->nDataLength;
//	LPTSTR lpszTarget;
//	while (lpszStart < lpszEnd)
//	{
//		while ((lpszTarget = _tcsstr(lpszStart, lpszOld)) != NULL)
//		{
//			nCount++;
//			lpszStart = lpszTarget + nSourceLen;
//		}
//		lpszStart += lstrlen(lpszStart) + 1;
//	}

//	// if any changes were made, make them
//	if (nCount > 0)
//	{
//		CopyBeforeWrite();

//		// if the buffer is too small, just
//		//   allocate a new buffer (slow but sure)
//		int nOldLength = GetData()->nDataLength;
//		int nNewLength =  nOldLength + (nReplacementLen-nSourceLen)*nCount;
//		if (GetData()->nAllocLength < nNewLength || GetData()->nRefs > 1)
//		{
//			CCStringData* pOldData = GetData();
//			LPTSTR pstr = m_pchData;
//			AllocBuffer(nNewLength);
//			memcpy(m_pchData, pstr, pOldData->nDataLength*sizeof(TCHAR));
//			CStrings::Release(pOldData);
//		}
//		// else, we just do it in-place
//		lpszStart = m_pchData;
//		lpszEnd = m_pchData + GetData()->nDataLength;

//		// loop again to actually do the work
//		while (lpszStart < lpszEnd)
//		{
//			while ( (lpszTarget = _tcsstr(lpszStart, lpszOld)) != NULL)
//			{
//				int nBalance = nOldLength - (lpszTarget - m_pchData + nSourceLen);
//				memmove(lpszTarget + nReplacementLen, lpszTarget + nSourceLen,
//					nBalance * sizeof(TCHAR));
//				memcpy(lpszTarget, lpszNew, nReplacementLen*sizeof(TCHAR));
//				lpszStart = lpszTarget + nReplacementLen;
//				lpszStart[nBalance] = '\0';
//				nOldLength += (nReplacementLen - nSourceLen);
//			}
//			lpszStart += lstrlen(lpszStart) + 1;
//		}
//		GetData()->nDataLength = nNewLength;
//	}

    std::string s1 = lpszOld;
    std::string s2 = lpszNew;
    if(s1 == s2)
        return nCount;

    std::string::size_type pos = 0;
    while((pos = m_pchData.find(s1)) != std::string::npos)
    {
        m_pchData.replace(pos, s1.length(), s2);
        ++nCount;
    }
	return nCount;
}

int CStrings::Remove(char chRemove)
{
//	CopyBeforeWrite();

//	LPTSTR pstrSource = m_pchData;
//	LPTSTR pstrDest = m_pchData;
//	LPTSTR pstrEnd = m_pchData + GetData()->nDataLength;

//	while (pstrSource < pstrEnd)
//	{
//		if (*pstrSource != chRemove)
//		{
//			*pstrDest = *pstrSource;
//			pstrDest = _tcsinc(pstrDest);
//		}
//		pstrSource = _tcsinc(pstrSource);
//	}
//	*pstrDest = '\0';
//	int nCount = pstrSource - pstrDest;
//	GetData()->nDataLength -= nCount;

    int nCount = 0;
    std::string::size_type pos;
    while((pos = m_pchData.find(chRemove)) != std::string::npos)
    {
          m_pchData.erase(pos);
          ++nCount;
    }
	return nCount;
}


//#################################################################################

//static void CConstructElements(CStrings* pElements, int nCount)
//{
//	for (; nCount--; ++pElements)
//		memcpy(pElements, &abcEmptyString, sizeof(*pElements));
//}
//static void DDestructElements(CStrings* pElements, int nCount)
//{
//	for (; nCount--; ++pElements)
//		pElements->~CStrings();
//}

//static void CCopyElements(CStrings* pDest, CStrings* pSrc, int nCount)
//{
//	while (nCount--)
//	{
//		*pDest = *pSrc;
//		++pDest;
//		++pSrc;
//	}
//}


CStringsArray::CStringsArray()
{
    //m_pData = NULL;
    //m_nSize = m_nMaxSize = m_nGrowBy = 0;
}

CStringsArray::~CStringsArray()
{
	 
    //DDestructElements(m_pData, m_nSize);
    //delete[] (BYTE*)m_pData;
}

CStrings CStringsArray::GetAt(int nIndex) const
{
	CStrings rr;
    if( nIndex >= 0 && nIndex < GetSize() )
		return m_pData[nIndex]; 
	else
		return rr; 
}

//void CStringsArray::SetSize(int nNewSize, int nGrowBy)
//{
//	if (nGrowBy != -1)
//		m_nGrowBy = nGrowBy;  // set new size

//	if (nNewSize == 0)
//	{
//		// shrink to nothing

//		DDestructElements(m_pData, m_nSize);
//		delete[] (BYTE*)m_pData;
//		m_pData = NULL;
//		m_nSize = m_nMaxSize = 0;
//	}
//	else if (m_pData == NULL)
//	{
//		// create one with exact size
//		m_pData = (CStrings*) new BYTE[nNewSize * sizeof(CStrings)];

//		CConstructElements(m_pData, nNewSize);
//		m_nSize = m_nMaxSize = nNewSize;
//	}
//	else if (nNewSize <= m_nMaxSize)
//	{
//		// it fits
//		if (nNewSize > m_nSize)
//		{
//			// initialize the new elements

//			CConstructElements(&m_pData[m_nSize], nNewSize-m_nSize);

//		}

//		else if (m_nSize > nNewSize)  // destroy the old elements
//			DDestructElements(&m_pData[nNewSize], m_nSize-nNewSize);

//		m_nSize = nNewSize;
//	}
//	else
//	{
//		// otherwise, grow array
//		int nGrowBy = m_nGrowBy;
//		if (nGrowBy == 0)
//		{
//			// heuristically determine growth when nGrowBy == 0
//			//  (this avoids heap fragmentation in many situations)
//			nGrowBy = min(1024, max(4, m_nSize / 8));
//		}
//		int nNewMax;
//		if (nNewSize < m_nMaxSize + nGrowBy)
//			nNewMax = m_nMaxSize + nGrowBy;  // granularity
//		else
//			nNewMax = nNewSize;  // no slush

//		CStrings* pNewData = (CStrings*) new BYTE[nNewMax * sizeof(CStrings)];

//		// copy new data from old
//		memcpy(pNewData, m_pData, m_nSize * sizeof(CStrings));

//		// construct remaining elements

//		CConstructElements(&pNewData[m_nSize], nNewSize-m_nSize);


//		// get rid of old stuff (note: no destructors called)
//		delete[] (BYTE*)m_pData;
//		m_pData = pNewData;
//		m_nSize = nNewSize;
//		m_nMaxSize = nNewMax;
//	}
//}

int CStringsArray::Append(const CStringsArray& src)
{
//	int nOldSize = m_nSize;
//	SetSize(m_nSize + src.m_nSize);

//	CCopyElements(m_pData + nOldSize, src.m_pData, src.m_nSize);

//	return nOldSize;
    int nOldSize = GetSize();
    for(auto const& entry : src.m_pData)
        m_pData.push_back(entry);
    return nOldSize;
}

//void CStringsArray::Copy(const CStringsArray& src)
//{
//	SetSize(src.m_nSize);
//	CCopyElements(m_pData, src.m_pData, src.m_nSize);
//}

//void CStringsArray::FreeExtra()
//{
	 

//	if (m_nSize != m_nMaxSize)
//	{
//		// shrink to desired size
//		CStrings* pNewData = NULL;
//		if (m_nSize != 0)
//		{
//			pNewData = (CStrings*) new BYTE[m_nSize * sizeof(CStrings)];
//			// copy new data from old
//			memcpy(pNewData, m_pData, m_nSize * sizeof(CStrings));
//		}

//		// get rid of old stuff (note: no destructors called)
//		delete[] (BYTE*)m_pData;
//		m_pData = pNewData;
//		m_nMaxSize = m_nSize;
//	}
//}

//void CStringsArray::SetAtGrow(int nIndex, LPCTSTR newElement)
//{
	 
//	if (nIndex >= m_nSize)
//		SetSize(nIndex+1);
//	m_pData[nIndex] = newElement;
//}

//void CStringsArray::SetAtGrow(int nIndex, const CStrings& newElement)
//{
//	if (nIndex >= m_nSize)
//		SetSize(nIndex+1);
//	m_pData[nIndex] = newElement;
//}

int CStringsArray::Add(LPCTSTR newElement)
{
//	int nIndex = m_nSize;
//	SetAtGrow(nIndex, newElement);
//	return nIndex;
    int nIndex = GetSize();
    m_pData.push_back(newElement);
    return nIndex;
}

//void CStringsArray::InsertEmpty(int nIndex, int nCount)
//{
//	if (nIndex >= m_nSize)
//	{
//		// adding after the end of the array
//		SetSize(nIndex + nCount);  // grow so nIndex is valid
//	}
//	else
//	{
//		// inserting in the middle of the array
//		int nOldSize = m_nSize;
//		SetSize(m_nSize + nCount);  // grow it to new size
//		// shift old data up to fill gap
//		memmove(&m_pData[nIndex+nCount], &m_pData[nIndex],
//			(nOldSize-nIndex) * sizeof(CStrings));

//		// re-init slots we copied from

//		CConstructElements(&m_pData[nIndex], nCount);

//	}
//}


void CStringsArray::InsertAt(int nIndex, LPCTSTR newElement, int nCount)
{
//	// make room for new elements
//	InsertEmpty(nIndex, nCount);
//	// copy elements into the empty space
//	CStrings temp = newElement;
//	while (nCount--)
//		m_pData[nIndex++] = temp;
    m_pData.insert(m_pData.begin() + nIndex, newElement);
}

void CStringsArray::InsertAt(int nIndex, const CStrings& newElement, int nCount)
{
	// make room for new elements
//	InsertEmpty(nIndex, nCount);

//	// copy elements into the empty space
//	while (nCount--)
//		m_pData[nIndex++] = newElement;
    m_pData.insert(m_pData.begin() + nIndex, newElement);
}


//void CStringsArray::RemoveAt(int nIndex, int nCount)
//{
//	// just remove a range
//	int nMoveCount = m_nSize - (nIndex + nCount);

//	DDestructElements(&m_pData[nIndex], nCount);

//	if (nMoveCount)
//		memmove(&m_pData[nIndex], &m_pData[nIndex + nCount],
//			nMoveCount * sizeof(CStrings));
//	m_nSize -= nCount;
//}

//void CStringsArray::InsertAt(int nStartIndex, CStringsArray* pNewArray)
//{
//	if (pNewArray->GetSize() > 0)
//	{
//		InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
//		for (int i = 0; i < pNewArray->GetSize(); i++)
//			SetAt(nStartIndex + i, pNewArray->GetAt(i));
//	}
//}

	
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

//////////////////////////////////////////////////////////////////////
// CArrays Class
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////



//////////////////////////////////////////////////////////////////////
// CMaps Class
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//CPlexs* PASCAL CPlexs::Create(CPlexs*& pHead, UINT nMax, UINT cbElement)
//{
//	CPlexs* p = (CPlexs*) new BYTE[sizeof(CPlexs) + nMax * cbElement];
//			// may throw exception
//	p->pNext = pHead;
//	pHead = p;  // change head (adds in reverse order for simplicity)
//	return p;
//}

//void CPlexs::FreeDataChain()     // free this one and links
//{
//	CPlexs* p = this;
//	while (p != NULL)
//	{
//		BYTE* bytes = (BYTE*) p;
//		CPlexs* pNext = p->pNext;
//		delete[] bytes;
//		p = pNext;
//	}
//}

//CFiles::CFiles()
//{
//	m_hFile = (UINT) hFileNull;
//	m_bCloseOnDelete = FALSE;
//}


//CFiles::CFiles(LPCTSTR lpszFileName, UINT nOpenFlags)
//{
//	Open(lpszFileName, nOpenFlags);
//}

//CFiles::~CFiles()
//{
//	if (m_hFile != (UINT)hFileNull && m_bCloseOnDelete)
//		Close();
//}

//void CFiles::Close()
//{
//	if (m_hFile != (UINT)hFileNull) CloseHandle( (HANDLE)m_hFile );
//	m_hFile = (UINT) hFileNull;
//	m_bCloseOnDelete = FALSE;
//}

//void CFiles::Abort()
//{
//	if (m_hFile != (UINT)hFileNull)
//	{
//		// close but ignore errors
//		::CloseHandle((HANDLE)m_hFile);
//		m_hFile = (UINT)hFileNull;
//	}
//}

//BOOL CFiles::Open( LPCTSTR lpszFileName, UINT nOpenFlags )
//{

//	// CFile objects are always binary and CreateFile does not need flag
//	nOpenFlags &= ~(UINT)typeBinary;

//	m_bCloseOnDelete = FALSE;
//	m_hFile = (UINT)hFileNull;

//	DWORD dwAccess = 0;
//	switch (nOpenFlags & 3)
//	{
//	case modeRead:
//		dwAccess = GENERIC_READ;
//		break;
//	case modeWrite:
//		dwAccess = GENERIC_WRITE;
//		break;
//	case modeReadWrite:
//		dwAccess = GENERIC_READ|GENERIC_WRITE;
//		break;
//	default:
//		dwAccess = GENERIC_READ;
//		break;
//	}

//	// map share mode
//	DWORD dwShareMode = 0;
//	switch (nOpenFlags & 0x70)    // map compatibility mode to exclusive
//	{
//	case shareCompat:
//	case shareExclusive:
//		dwShareMode = 0;
//		break;
//	case shareDenyWrite:
//		dwShareMode = FILE_SHARE_READ;
//		break;
//	case shareDenyRead:
//		dwShareMode = FILE_SHARE_WRITE;
//		break;
//	case shareDenyNone:
//		dwShareMode = FILE_SHARE_WRITE|FILE_SHARE_READ;
//		break;
//	default:
//		dwShareMode = FILE_SHARE_WRITE|FILE_SHARE_READ;
//		break;
//	}

//	DWORD dwCreateFlag;
//	if (nOpenFlags & modeCreate)
//	{
//		if (nOpenFlags & modeNoTruncate)
//			dwCreateFlag = OPEN_ALWAYS;
//		else
//			dwCreateFlag = CREATE_ALWAYS;
//	}
//	else
//		dwCreateFlag = OPEN_EXISTING;

//	// attempt file creation
//	HANDLE hFile = ::CreateFile(lpszFileName, dwAccess, dwShareMode, NULL,
//		dwCreateFlag, FILE_ATTRIBUTE_NORMAL, NULL);
//	if (hFile == INVALID_HANDLE_VALUE)
//	{
//		return FALSE;
//	}
//	m_hFile = (HFILE)hFile;
//	m_bCloseOnDelete = TRUE;

//	return TRUE;
//}

//DWORD CFiles::SeekToEnd()
//{
//	return Seek(0, CFiles::end);
//}
//void CFiles::SeekToBegin()
//{
//	Seek(0, CFiles::begin);
//}

//DWORD CFiles::Seek(LONG lOff, UINT nFrom)
//{
//	DWORD dwNew = ::SetFilePointer((HANDLE)m_hFile, lOff, NULL, (DWORD)nFrom);
//	return dwNew;
//}

//DWORD CFiles::GetLength() const
//{
//	DWORD dwLen, dwCur;

//	// Seek is a non const operation
//	CFiles* pFile = (CFiles*)this;
//	dwCur = pFile->Seek(0L, current);
//	dwLen = pFile->SeekToEnd();
//	pFile->Seek(dwCur, begin);

//	return dwLen;
//}

//UINT CFiles::Read(void* lpBuf, UINT nCount)
//{

//	if (nCount == 0) return 0;
//	DWORD dwRead;
//	::ReadFile((HANDLE)m_hFile, lpBuf, nCount, &dwRead, NULL);
//	return (UINT)dwRead;
//}

//void CFiles::Write(const void* lpBuf, UINT nCount)
//{
//	if (nCount == 0) return;
//	DWORD nWritten;
//	::WriteFile((HANDLE)m_hFile, lpBuf, nCount, &nWritten, NULL);
//}


//CStdioFiles::CStdioFile()
//{
//	m_pStream = NULL;
//}

//CStdioFiles::CStdioFile(FILE* pOpenStream)
//{
//	m_pStream = pOpenStream;
//	m_hFile = (UINT)_get_osfhandle(_fileno(pOpenStream));
//}

//CStdioFiles::CStdioFile(LPCTSTR lpszFileName, UINT nOpenFlags)
//{
//	Open(lpszFileName, nOpenFlags);
//}

//CStdioFiles::~CStdioFile()
//{
//	if (m_pStream != NULL && m_bCloseOnDelete)
//		Close();
//}

//BOOL CStdioFiles::Open(LPCTSTR lpszFileName, UINT nOpenFlags)
//{
//	m_pStream = NULL;
//	if (!CFile::Open(lpszFileName, (nOpenFlags & ~typeText)))
//		return FALSE;

//	char szMode[4]; // C-runtime open string
//	int nMode = 0;

//	// determine read/write mode depending on CFile mode
//	if (nOpenFlags & modeCreate)
//	{
//		if (nOpenFlags & modeNoTruncate)
//			szMode[nMode++] = 'a';
//		else
//			szMode[nMode++] = 'w';
//	}
//	else if (nOpenFlags & modeWrite)
//		szMode[nMode++] = 'a';
//	else
//		szMode[nMode++] = 'r';

//	// add '+' if necessary (when read/write modes mismatched)
//	if (szMode[0] == 'r' && (nOpenFlags & modeReadWrite) ||
//		szMode[0] != 'r' && !(nOpenFlags & modeWrite))
//	{
//		// current szMode mismatched, need to add '+' to fix
//		szMode[nMode++] = '+';
//	}

//	// will be inverted if not necessary
//	int nFlags = _O_RDONLY|_O_TEXT;
//	if (nOpenFlags & (modeWrite|modeReadWrite))
//		nFlags ^= _O_RDONLY;

//	if (nOpenFlags & typeBinary)
//		szMode[nMode++] = 'b', nFlags ^= _O_TEXT;
//	else
//		szMode[nMode++] = 't';
//	szMode[nMode++] = '\0';

//	// open a C-runtime low-level file handle
//	int nHandle = _open_osfhandle(m_hFile, nFlags);

//	// open a C-runtime stream from that handle
//	if (nHandle != -1)
//		m_pStream = _fdopen(nHandle, szMode);

//	if (m_pStream == NULL)
//	{
//		// an error somewhere along the way...

//		CFiles::Abort(); // close m_hFile
//		return FALSE;
//	}

//	return TRUE;
//}

//UINT CStdioFiles::Read(void* lpBuf, UINT nCount)
//{
//	if (nCount == 0)
//		return 0;   // avoid Win32 "null-read"

//	UINT nRead = 0;

//	nRead = fread(lpBuf, sizeof(BYTE), nCount, m_pStream);
//	if (ferror(m_pStream))
//	{
//		clearerr(m_pStream);
//	}
//	return nRead;
//}

//void CStdioFiles::Write(const void* lpBuf, UINT nCount)
//{
//	fwrite(lpBuf, sizeof(BYTE), nCount, m_pStream);
//}

//void CStdioFiles::WriteString(LPCTSTR lpsz)
//{
//	_fputts(lpsz, m_pStream);
//}

//LPTSTR CStdioFiles::ReadString(LPTSTR lpsz, UINT nMax)
//{
//	LPTSTR lpszResult = _fgetts(lpsz, nMax, m_pStream);
//	if (lpszResult == NULL && !feof(m_pStream))
//	{
//		clearerr(m_pStream);
//	}
//	return lpszResult;
//}

//BOOL CStdioFiles::ReadString(CString& rString)
//{
//	rString = &abcChNil;    // empty string without deallocating
//	const int nMaxSize = 128;
//	LPTSTR lpsz = rString.GetBuffer(nMaxSize);
//	LPTSTR lpszResult;
//	int nLen = 0;
//	for (;;)
//	{
//		lpszResult = _fgetts(lpsz, nMaxSize+1, m_pStream);
//		rString.ReleaseBuffer();

//		// handle error/eof case
//		if (lpszResult == NULL && !feof(m_pStream))
//		{
//			clearerr(m_pStream);
//		}

//		// if string is read completely or EOF
//		if (lpszResult == NULL ||
//			(nLen = lstrlen(lpsz)) < nMaxSize ||
//			lpsz[nLen-1] == '\n')
//			break;

//		nLen = rString.GetLength();
//		lpsz = rString.GetBuffer(nMaxSize + nLen) + nLen;
//	}

//	// remove '\n' from end of string if present
//	lpsz = rString.GetBuffer(0);
//	nLen = rString.GetLength();
//	if (nLen != 0 && lpsz[nLen-1] == '\n')
//		rString.GetBufferSetLength(nLen-1);

//	return lpszResult != NULL;
//}

//LONG CStdioFiles::Seek(LONG lOff, UINT nFrom)
//{
//	fseek(m_pStream, lOff, nFrom);
//	long pos = ftell(m_pStream);
//	return pos;
//}

//DWORD CStdioFiles::GetPosition() const
//{
//	long pos = ftell(m_pStream);
//	return pos;
//}

//void CStdioFiles::Flush()
//{

//	if (m_pStream != NULL ) fflush(m_pStream);
//}

//void CStdioFiles::Close()
//{
//	int nErr = 0;

//	if (m_pStream != NULL)
//		nErr = fclose(m_pStream);

//	m_hFile = (UINT) hFileNull;
//	m_bCloseOnDelete = FALSE;
//	m_pStream = NULL;
//}

//void CStdioFiles::Abort()
//{
//	if (m_pStream != NULL && m_bCloseOnDelete)
//		fclose(m_pStream);  // close but ignore errors
//	m_hFile = (UINT) hFileNull;
//	m_pStream = NULL;
//	m_bCloseOnDelete = FALSE;
//}

